package models

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"time"

	"gitee.com/lzqysoft/ims/libs"
	"gitee.com/lzqysoft/ims/libs/encrypt"
	"gitee.com/lzqysoft/ims/libs/fsm"
	"gitee.com/lzqysoft/ims/libs/strtool"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

type Flowinstance struct {
	Id                 string                `orm:"column(id);pk"`
	Flow               *Flow                 `orm:"column(flow_id);rel(fk)"`
	Name               string                `orm:"column(name);null"`
	Busyid             string                `orm:"column(busyid);null"`
	Busyname           string                `orm:"column(busyname);null"`
	Level              int                   `orm:"column(level);null"`
	Start              string                `orm:"column(start);null"`
	End                string                `orm:"column(end);null"`
	Currentstate       string                `orm:"column(currentstate);null"`
	Remark             string                `orm:"column(remark);null"`
	Status             int                   `orm:"column(status)"`
	Isdelete           int                   `orm:"column(isdelete)"`
	Ctime              time.Time             `orm:"column(ctime);type(timestamp with time zone)"`
	Creater            string                `orm:"column(creater)"`
	Utime              time.Time             `orm:"column(utime);type(timestamp with time zone)"`
	Updater            string                `orm:"column(updater)"`
	UserId             string                `orm:"column(user_id)"`
	Stateinstance      []*Stateinstance      `orm:"reverse(many)"`
	TransitionInstance []*TransitionInstance `orm:"reverse(many)"`
}

func (t *Flowinstance) TableName() string {
	return "fsm_flowinstance"
}

func NewFlowinstance() *Flowinstance {
	return &Flowinstance{
		Id:       libs.UUID(),
		Status:   1,
		Isdelete: 0,
		Ctime:    time.Now(),
		Utime:    time.Now(),
	}
}
func init() {
	orm.RegisterModel(new(Flowinstance))
}

// AddFlowinstance insert a new Flowinstance into database and returns
// last inserted Id on success.
func AddFlowinstance(m *Flowinstance) (id int64, err error) {
	o := orm.NewOrm()
	id, err = o.Insert(m)
	return
}

// GetFlowinstanceById retrieves Flowinstance by Id. Returns error if
// Id doesn't exist
func GetFlowinstanceById(id string) (v *Flowinstance, err error) {
	o := orm.NewOrm()
	v = &Flowinstance{Id: id}
	if err = o.Read(v); err == nil {
		return v, nil
	}
	return nil, err
}

// GetFlowinstanceByBusyId 根据业务id获取流程实例
func GetFlowinstanceByBusyId(id string) (v *Flowinstance, err error) {
	o := orm.NewOrm()
	v = &Flowinstance{Busyid: id}
	if err = o.Read(v, "Busyid"); err == nil {
		o.LoadRelated(v, "Stateinstance")
		o.LoadRelated(v, "TransitionInstance")
		return v, nil
	}
	beego.Debug(err)
	return nil, err
}

// GetAllFlowinstance retrieves all Flowinstance matches certain condition. Returns empty list if
// no records exist
func GetAllFlowinstance(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Flowinstance))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		if strings.Contains(k, "isnull") {
			qs = qs.Filter(k, (v == "true" || v == "1"))
		} else {
			qs = qs.Filter(k, v)
		}
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			// 2) there is exactly one order, all the sorted fields will be sorted by this order
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []Flowinstance
	qs = qs.OrderBy(sortFields...)
	if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				for _, fname := range fields {
					m[fname] = val.FieldByName(fname).Interface()
				}
				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateFlowinstance updates Flowinstance by Id and returns error if
// the record to be updated doesn't exist
func UpdateFlowinstanceById(m *Flowinstance) (err error) {
	o := orm.NewOrm()
	v := Flowinstance{Id: m.Id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Update(m); err == nil {
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}

// DeleteFlowinstance deletes Flowinstance by Id and returns error if
// the record to be deleted doesn't exist
func DeleteFlowinstance(id string) (err error) {
	o := orm.NewOrm()
	v := Flowinstance{Id: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&Flowinstance{Id: id}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}

// GetFlowinstanceBybusy 根据业务名称和业务id获取流程实例
func GetFlowinstanceBybusy(bname string, id string) (v *Flowinstance, err error) {
	beego.Debug(bname, id)
	o := orm.NewOrm()
	v = &Flowinstance{Busyname: bname, Busyid: id, Status: 1}
	if err = o.Read(v, "Busyname", "Busyid", "Status"); err == nil {
		return v, nil
	}
	return nil, err
}

//
func GetFlowinstanceBybusyStatus(bname string, id string) (v *Flowinstance, err error) {
	beego.Debug(bname, id)
	o := orm.NewOrm()
	v = &Flowinstance{Busyname: bname, Busyid: id, Status: 1}
	if err = o.Read(v, "Busyname", "Busyid", "Status"); err == nil {
		return v, nil
	}
	return nil, err
}

// GetFlowinstanceBybusyRewrite 根据业务名称和业务id获取流程实例
func GetFlowinstanceBybusyRewrite(bname string, id string) (v *Flowinstance, err error) {
	beego.Debug(bname, id)
	o := orm.NewOrm()
	pf := &ImsProjectFlow{ProjectId: id, Status: 1}
	if err := o.Read(pf, "ProjectId", "Status"); err != nil {
		return nil, err
	}
	v = &Flowinstance{}
	o.QueryTable(new(Flowinstance)).Filter("Busyname", bname).Filter("Busyid", pf.Id).One(v)
	if err = o.Read(v); err == nil {
		return v, nil
	}
	return nil, err
}

////FlowInstance 流程对象
//type FlowInstance struct {
//	ID         uint64
//	EventCount uint64
//	CoinCount  uint64
//	PassCount  uint64
//	State      string
//	States     []string
//}

// FlowEventProcessor 用于处理FlowInstance动作。
type FlowEventProcessor struct{}

// OnExit 离开fromstate时的动作。
func (p *FlowEventProcessor) OnExit(fromState string, args []interface{}) {
	//t := args[0].(*Flowinstance)
	//// if t.Currentstate != fromState {
	//// 	panic(fmt.Errorf("流程 %v 的状态与期望的状态 %s 不一致，可能在状态机外被改变了", t, fromState))
	//// }
	//beego.Debug("流程 ", t.Name, " 从状态 ", fromState, " 改变")
}

// Action 流程转换被处理的时候，状态机会执行特定的动作，
// 比如改变变量、执行I/O、调用方法、触发另一个事件等。
// 此处流程动作为向to流程责任人发送信息，from状态为2,to状态为1
// 若to类型为end，将流程实例状态改为2,标识已完成
func (p *FlowEventProcessor) Action(action, fromState, toState string, args []interface{}) {
	f := args[0].(*Flowinstance)
	user := args[1].(*User)
	opinions := args[2].(string)
	remark := args[3].(string)
	f.Currentstate = toState
	f.Utime = time.Now()
	from, _ := GetStateinstanceById(fromState)
	to, _ := GetStateinstanceById(toState)
	o := orm.NewOrm()
	err := o.Begin()
	if to.Classname == "end" {
		f.Status = 2
		beego.Debug(f)
		if f.Busyname == "yjk_buy" {
			beego.Debug("这是一个采购单，将生成入库单,入库单确认后，生成付款单")
			buy, err := GetBuyById(f.Busyid)
			beego.Error(err)
			sinId, err := InsertSinByBusy(buy)
			beego.Error(err)
			// 添加入库单
			err = InsertInsByBuyAndSin(buy.Id, sinId)
			beego.Error(err)
			// 启用付款单
			err = StartPay(f.Busyid)
			beego.Error(err)

		} else if f.Busyname == "sf_engineer_instance" {
			beego.Debug("这是一个技术人员变更记录")
			instance, err := GetSfEngineerInstanceById(f.Busyid)
			beego.Error(err)
			items, err := GetInstanceItemByInstanceId(instance.Id)
			beego.Debug(items)
			beego.Debug(len(items))
			var egs []Engineer

			for _, v := range items {
				var e Engineer
				if v.OperateType == 0 {
					e.Id = libs.UUID()
				} else {
					e.Id = v.EngineerId
				}

				e.DeptId = v.DeptId
				e.Remark = v.Remark
				e.Status = 1
				e.Ctime = time.Now()
				e.Utime = time.Now()
				e.Creater = v.Creater
				e.Updater = v.Updater
				e.Sex = v.Sex
				e.Name = v.Name
				e.Birth = v.Birth
				e.Xueli = v.Xueli
				e.Xuelihuode = v.Xuelihuode
				e.Biyeyuanxiaojizhuanye = v.Biyeyuanxiaojizhuanye
				e.Biyeshijian = v.Biyeshijian
				e.Gongzuoshijiandanwei = v.Gongzuoshijiandanwei
				e.Jishugongzuoshijiandanwei = v.Jishugongzuoshijiandanwei
				e.Jaindingzige = v.Jaindingzige
				e.Xianzhuanye = v.Xianzhuanye
				e.Qudejishuzigeshijian = v.Qudejishuzigeshijian
				e.Suozaibumen = v.Suozaibumen
				e.Kancha = v.Kancha
				egs = append(egs, e)
			}
			switch instance.Optype {
			case 0:
				// create
				EngineerInsertMulit(egs)
			case 1:
				// udpate
				EngineerUpdateMulit(egs)
			case 2:
				// delete
				EngineerDeleteMulit(egs)
			default:
				// 不做任何操作
			}
		} else if f.Busyname == "sf_sfyy" {
			beego.Debug("这是一个检验审批记录")
		} else if f.Busyname == "sf_case" {
			beego.Debug("这是一个检验审批记录sf_case")
			sfCase, _ := GetSfCaseById(f.Busyid)
			//sfCase.Status = 2 预约中
			sfCase.Status = 3 // 待取件
			UpdateSfCaseById(sfCase)

		} else {
			beego.Debug("这是一个销售订单，将生成出库单与付收款单！")
			order, err := GetOrderById(f.Busyid)
			beego.Debug(err)
			soutId, err := InsertSoutByBusy(order)
			beego.Error(err)
			// 添加出库单
			err = InsertOutsByBuyAndSout(order.Id, soutId)
			beego.Error(err)
			// 启用收款单
			err = StartReceiv(f.Busyid)
			beego.Error(err)
		}
	}
	if to.Classname == "start" {
		f.Status = 3
	}
	to.Status = 1
	to.Utime = time.Now()
	from.Status = 2
	from.Opinions = opinions
	from.Remark = remark
	from.Utime = time.Now()
	from.Approver = user.Abbr
	from.Atime = time.Now()
	switch action {
	case "1":
		// 提醒
		var mes Message
		mes.BusyId = f.Id
		mes.Busy = f.Busyname
		mes.Title = "待办信息"
		mes.Isread = 0
		mes.Content = fmt.Sprintf("您有一个 %s 审批事务需要处理", f.Name)
		mes.Ctime = time.Now()
		mes.Utime = time.Now()
		mes.Creater = "admin"
		mes.Updater = "admin"
		mes.Id = encrypt.GetGuid()
		mes.User, _ = GetUserById(to.UserId)
		_, err := o.Insert(&mes)
		if err != nil {
			beego.Error(err)
		}

		var rec Message
		rec.BusyId = f.Id
		rec.Busy = f.Busyname
		rec.Title = "流程信息"
		rec.Isread = 0
		rec.Content = fmt.Sprintf("您的%s审批信息已变更", f.Name)
		rec.Ctime = time.Now()
		rec.Utime = time.Now()
		rec.Creater = "admin"
		rec.Updater = "admin"
		rec.Id = encrypt.GetGuid()
		rec.User, _ = GetUserById(f.UserId)
		_, err = o.Insert(&rec)
		if err != nil {
			beego.Error(err)
		}
	case "7":
		// 新建单据
		if f.Busyname == "sf_case" {
			sfCase, _ := GetSfCaseById(f.Busyid)
			SfCaseItems, _ := GetSfCaseItemsBySfCase(sfCase.Id)
			appointer, _ := GetUserById(f.UserId)
			item := SfCaseItems[0]
			mtodo := GenerateSfTodoManager()
			mtodo.BusyName = f.Busyname
			mtodo.BusyId = f.Busyid
			mtodo.Type = 0
			mtodo.Remark = item.Remark
			mtodo.Title = sfCase.Title
			mtodo.RoleId = user.Role[0].Id
			mtodo.JyType = sfCase.JyType
			mtodo.Creater = appointer.Abbr
			mtodo.Name = libs.GetMTodoTitleByType(0)
			mtodo.Ctime = sfCase.AppointTime
			mtodo.Content = item.Remark
			beego.Debug("item.Remark", item.Remark)
			//mtodo.RoleId =
			o.Insert(mtodo)
			utodo := GenerateSfTodouser()
			utodo.Type = 0
			utodo.Name = libs.GetUTodoTitleByType(0)
			utodo.UserId = f.UserId
			utodo.Title = sfCase.Title
			utodo.Content = sfCase.Title + "有一个" + libs.GetUTodoTitleByType(0) + "事项"
			utodo.BusyName = f.Busyname
			utodo.BusyId = f.Busyid
			o.Insert(utodo)
		}
	case "8":
		beego.Debug("并入单据")
		// 并入单据
		if f.Busyname == "sf_case" {
			sfCase, _ := GetSfCaseById(f.Busyid)
			SfCaseItems, _ := GetSfCaseItemsBySfCase(sfCase.Id)
			appointer, _ := GetUserById(f.UserId)
			item := SfCaseItems[0]
			item.Addition = 1
			UpdateSfCaseItemById(&item)
			mtodo := GenerateSfTodoManager()
			mtodo.BusyName = f.Busyname
			mtodo.BusyId = f.Busyid
			mtodo.Type = 0
			mtodo.Remark = item.Remark
			mtodo.Title = sfCase.Title
			mtodo.RoleId = user.Role[0].Id
			mtodo.JyType = sfCase.JyType
			mtodo.Creater = appointer.Abbr
			mtodo.Name = libs.GetMTodoTitleByType(0)
			mtodo.Ctime = sfCase.AppointTime
			mtodo.Content = item.Remark
			beego.Debug("item.Remark", item.Remark)
			//mtodo.RoleId =
			o.Insert(mtodo)
			utodo := GenerateSfTodouser()
			utodo.Type = 0
			utodo.Name = libs.GetUTodoTitleByType(0)
			utodo.UserId = f.UserId
			utodo.Title = sfCase.Title
			utodo.Content = sfCase.Title + "有一个" + libs.GetUTodoTitleByType(0) + "事项"
			utodo.BusyName = f.Busyname
			utodo.BusyId = f.Busyid
			o.Insert(utodo)
		}
	default:
	}
	_, err = o.Update(f)
	if err != nil {
		beego.Error(err)
		err = o.Rollback()
	}
	_, err = o.Update(to)
	if err != nil {
		beego.Error(err)
		err = o.Rollback()
	}
	_, err = o.Update(from)
	if err != nil {
		beego.Error(err)
		err = o.Rollback()
	}
	err = o.Commit()
	beego.Info("流程 ", f.Name, " 的状态从 ", from.Text, " 改变为  ", to.Text)
	beego.Debug("from ", from.Status)
}

//OnEnter 进入一个状态，可以执行的动作,此处添加提醒消息
func (p *FlowEventProcessor) OnEnter(toState string, args []interface{}) {
	f := args[0].(*Flowinstance)
	to, _ := GetStateinstanceById(toState)
	o := orm.NewOrm()
	switch to.Classname {
	case "end":
		beego.Debug("结束")
		f.Status = 2
	case "start":
		beego.Debug("开始")
		f.Status = 3
	case "fork":
		beego.Debug("分派任务")
		// f.Currentstate = toState
		fs := GetFSM(f)
		ev, _ := GetEventByName("分派")
		err := fs.Trigger(toState, ev.Id, args...)
		if err != nil {
			beego.Error("聚合 err: ", err)
		}
	case "join":
		beego.Debug("汇聚任务")
		beego.Debug(toState)
		ts, _ := GetFromByFork(toState)
		status := 1
		for _, k := range ts {
			tins, _ := GetStateinstanceById(k.Id)
			beego.Debug(tins)
			if tins.Status == 2 {
				if tins.Result == 1 {
					status = 2
				} else {
					status = 3
				}
			} else {
				status = 1
			}
		}
		if status == 2 {
			fs := GetFSM(f)
			ev, _ := GetEventByName("聚合")
			err := fs.Trigger(toState, ev.Id, args...)
			if err != nil {
				beego.Error("聚合同意 err: ", err)
			}
		}
		if status == 3 {
			fs := GetFSM(f)
			ev, _ := GetEventByName("不同意")
			err := fs.Trigger(toState, ev.Id, args...)
			if err != nil {
				beego.Error("聚合不同意 err: ", err)
			}
		}
	case "auto":
		beego.Debug("自动任务")
		fs := GetFSM(f)
		if f.Busyname == "sf_case" {
			fsCase, _ := GetSfCaseById(f.Busyid)
			//if err != nil {
			//	beego.Error("自动任务", err)
			//}
			if fsCase.IsAdditional != 1 {
				//  检验预约自动任务
				ev, _ := GetEventByName("否")
				fs.Trigger(toState, ev.Id, args...)
			} else {
				ev, _ := GetEventByName("是")
				//  检验补充送检预约自动任务
				fs.Trigger(toState, ev.Id, args...)
			}
		}

	}

	_, err := o.Update(f)
	if err != nil {
		beego.Error(err)
	}
	// _, err = o.Update(to)
	// if err != nil {
	// 	beego.Error(err)
	// }
}

//InitFSM 根据业务名称，业务id和流程级别创建流程实例
func InitFSM(user *User, flow_id, busyname, busyid string) (f *Flowinstance, err error) {
	//	f := new(Flowinstance)
	// f, err = GetFlowinstanceBybusy(busyname, busyid)
	// if err == nil {
	// 	return nil, errors.New("流程实例已存在！")
	// }
	var fs Flowinstance
	flow, err := GetFlowById(flow_id)
	if err != nil {
		return nil, err
	}
	states, err := GetStateByFlow(flow_id)
	if err != nil {
		return nil, err
	}
	//插入流程实例
	o := orm.NewOrm()
	//o.Begin()
	fs.Busyname = busyname
	fs.Name = flow.Name
	fs.Busyid = busyid
	fs.Flow = flow
	// f.Level = level
	fs.Creater = user.Name
	fs.Updater = user.Name
	fs.Ctime = time.Now()
	fs.Utime = time.Now()
	fs.Id = encrypt.GetGuid()
	fs.Status = 1
	fs.Isdelete = 0
	fs.UserId = user.Id

	// flowins, _ := GetFlowinstanceById(f.Id)

	//插入状态实例
	var stateIns Stateinstance
	for _, v := range states {
		stateIns.Text = v.Text
		//		stateIns.Role = v.Role
		stateIns.Flowinstance = &fs
		// stateIns.Busyid = busyid
		// stateIns.Busyname = busyname
		stateIns.Remark = v.Remark
		stateIns.Status = v.Status
		stateIns.Classname = v.Classname
		stateIns.Creater = user.Name
		stateIns.Updater = user.Name
		stateIns.Ctime = time.Now()
		stateIns.Utime = time.Now()
		stateIns.State = &v
		stateIns.Id = encrypt.GetGuid()
		stateIns.Status = 0
		stateIns.Style = v.Style
		stateIns.Isdelete = 0
		stateIns.Busyid = fs.Busyid
		stateIns.Busyname = fs.Busyname
		switch v.Classname {
		case "start":
			stateIns.UserId = user.Id
			fs.Start = stateIns.Id
			fs.Currentstate = stateIns.Id
			stateIns.Status = 1
		case "end":
			stateIns.UserId = ""
			fs.End = stateIns.Id
		case "join":
			stateIns.UserId = ""
		case "fork":
			stateIns.UserId = ""
		case "auto":
			stateIns.UserId = ""
		default:
			beego.Debug("人工任务")
			beego.Debug(v)
			beego.Debug("busyname", busyname, "busyid", busyid)

			if busyname == "sf_case" {
				users, err := GetUserByOrgRoelList(user.Organization.Id, v.RoleId)
				beego.Debug(users)
				if err != nil {
					beego.Error(err)
					o.Rollback()
					return nil, err
				}
				deepuser, _ := GetUserById(users[0].Id)
				stateIns.UserId = deepuser.Role[0].Id
			} else {
				us, err := GetUserByOrgRoel(user.Organization.Id, v.RoleId)
				beego.Debug(us)
				if err != nil {
					beego.Error(err)
					o.Rollback()
					return nil, err
				}
				stateIns.UserId = us.Id
			}
		}
		_, err = o.Insert(&stateIns)
		if err != nil {
			beego.Error(err)
			//o.Rollback()
			return nil, err
		}
	}
	_, err = o.Insert(&fs)
	if err != nil {
		beego.Error(err)
		//o.Rollback()
		return nil, err
	}
	//创建转换实例
	trans, _ := GetTransByFlow(flow.Id)
	// beego.Debug(trans)
	var ts TransitionInstance
	for _, t := range trans {
		ts.Action = t.Action
		ts.Creater = user.Name
		ts.Ctime = time.Now()
		ts.EventId = t.EventId
		ts.Flow = t.Flow
		ts.Flowinstance = &fs
		from, err := GetStateinstanceByFlowInsAndState(fs.Id, t.From)
		if err != nil {
			beego.Error(err)
			//o.Rollback()
			return nil, err
		}
		to, err := GetStateinstanceByFlowInsAndState(fs.Id, t.To)
		if err != nil {
			beego.Error(err)
			//o.Rollback()
			return nil, err
		}
		ts.From = from.Id
		ts.To = to.Id
		fstr := strtool.GetBetweenStr(t.Fromid, "$")
		ts.Fromid = ts.From + fstr
		tstr := strtool.GetBetweenStr(t.Toid, "$")
		ts.Toid = ts.To + tstr
		ts.Id = encrypt.GetGuid()
		ts.Isdelete = 0
		ts.Status = 1
		ts.Name = t.Name
		ts.Transition = t
		ts.Updater = user.Name
		ts.Utime = ts.Ctime
		_, err = o.Insert(&ts)
		if err != nil {
			beego.Error(err)
			//o.Rollback()
			return nil, err
		}
	}
	//err = o.Commit()
	beego.Debug("流程初始化完成", err)
	return &fs, err
}

// InitializationFsm 初始化流程流程节点，转化关系等...
func InitializationFsm(user *User, flowId, busyname, busyId string) (*Flowinstance, error) {
	o := orm.NewOrm()
	o.Begin()
	flow, err := GetFlowById(flowId)
	if err != nil {
		beego.Debug(err)
		return nil, err
	}
	// 创建流程实例
	fs := NewFlowinstance()
	fs.Busyname = busyname
	fs.Name = flow.Name
	fs.Busyid = busyId
	fs.Flow = flow
	// f.Level = level
	fs.UserId = user.Id
	if _, err := o.Insert(fs); err != nil {
		beego.Debug(err)
		o.Rollback()
		return nil, err
	}

	// 创建流程状态实例的开始节点
	//startState, err := GetStartStateByFLow(flow.Id)
	startState, err := GetStateById(flow.Start)
	if err != nil {
		beego.Debug(err)
		o.Rollback()
		return nil, err
	}
	startStateInstance := NewStateinstance()
	SyncStateAndStateInstance(startState, startStateInstance)
	startStateInstance.Flowinstance = fs
	startStateInstance.Creater = user.Name
	startStateInstance.Updater = user.Name
	startStateInstance.State = startState
	startStateInstance.Busyid = fs.Busyid
	startStateInstance.Busyname = fs.Busyname
	startStateInstance.UserId = user.Id
	if _, err = o.Insert(startStateInstance); err != nil {
		beego.Debug(err)
		o.Rollback()
		return nil, err
	}
	// 创建可能转换的流程实例
	//if err = autoGenerateStateInstance(o, fs, startStateInstance, user); err != nil {
	//	beego.Debug(err)
	//	o.Rollback()
	//	return nil, err
	//}
	//fs.Currentstate = startStateInstance.Id
	if err = autoGenerateStateInstanceAndTransitionInstance(o, fs, startStateInstance, user, make(map[string]interface{})); err != nil {
		beego.Debug(err)
		o.Rollback()
		return nil, err
	}
	fs.Currentstate = startStateInstance.Id
	fs.Start = startStateInstance.Id
	if _, err := o.Update(fs); err != nil {
		beego.Debug(err)
		o.Rollback()
		return nil, err
	}
	//if err = UpdateFlowinstanceById(fs); err != nil {
	//	beego.Debug(err)
	//	o.Rollback()
	//	return nil, err
	//}
	// 创建流程状态转换关系
	//if err = autoGenerateTransitionInstance(o, fs, startStateInstance, user); err != nil {
	//	beego.Debug(err)
	//	o.Rollback()
	//	return nil, err
	//}
	return fs, o.Commit()
}

//GetFSM 初始化流程生成一个流程的所有状态的转换规则
//func FSM() {
//	ts := models.Flowinstance
//	fsm := GetFSM(ts)

//	//推门
//	//没刷卡/投币不可进入
//	err := fsm.Trigger(ts.Currentstate, "Push", ts)
//	if err != nil {
//		fmt.Printf("trigger err: %v", err)
//	}
//fsm.Export("state.png")

//	//推门
//	//没刷卡/投币不可进入
//	err = fsm.Trigger(ts.State, "Push", ts)
//	if err != nil {
//		fmt.Printf("trigger err: %v", err)
//	}

//	//刷卡或者投币
//	//不容易啊，终于解锁了
//	err = fsm.Trigger(ts.State, "Coin", ts)
//	if err != nil {
//		fmt.Printf("trigger err: %v", err)
//	}

//	//刷卡或者投币
//	//这时才解锁
//	err = fsm.Trigger(ts.State, "Coin", ts)
//	if err != nil {
//		fmt.Printf("trigger err: %v", err)
//	}

//	//推门
//	//这时才能进入，进入后闸门被锁
//	err = fsm.Trigger(ts.State, "Push", ts)
//	if err != nil {
//		fmt.Printf("trigger err: %v", err)
//	}

//	//推门
//	//无法进入，闸门已锁
//	err = fsm.Trigger(ts.State, "Push", ts)
//	if err != nil {
//		fmt.Printf("trigger err: %v", err)
//	}

//	lastState := Turnstile{
//		ID:         1,
//		EventCount: 6,
//		CoinCount:  2,
//		PassCount:  1,
//		State:      "Locked",
//		States:     []string{"Locked", "Unlocked", "Locked"},
//	}

//	if !compareTurnstile(&lastState, ts) {
//		fmt.Printf("Expected last state: %+v, but got %+v", lastState, ts)
//	} else {
//		fmt.Printf("最终的状态: %+v", ts)
//	}
//}

//GetFSM 获取流程实例状态机。
func GetFSM(flowins *Flowinstance) *fsm.StateMachine {
	delegate := &fsm.DefaultDelegate{P: &FlowEventProcessor{}}
	beego.Debug(flowins.Flow)
	t, err := GetTransitionInstanceByFlow(flowins.Id)
	transitions := []fsm.Transition{}
	if err != nil {
		return nil
	}
	for _, u := range t {
		var f fsm.Transition
		f.From = u["From"].(string)
		f.To = u["To"].(string)
		f.Action = u["Action"].(string)
		f.Event = u["Event"].(string)
		f.FromName = u["FromName"].(string)
		f.ToName = u["ToName"].(string)
		f.ActionName = u["ActionName"].(string)
		f.EventName = u["EventName"].(string)
		transitions = append(transitions, f)
	}

	//	transitions := []fsm.Transition{
	//		{From: 1, Event: 1, To: 2, Action: 1},
	//		{From: 2, Event: 2, To: 3, Action: 2},
	//		{From: 2, Event: 3, To: 1, Action: 3},
	//		{From: 3, Event: 4, To: 4, Action: 4},
	//	}
	// beego.Debug(transitions)
	return fsm.NewStateMachine(delegate, transitions...)

}
